/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.tools.idea.uibuilder.visual

import com.android.tools.configurations.Configuration
import com.android.tools.configurations.ConfigurationListener
import com.android.tools.idea.common.model.NlModel
import com.intellij.openapi.util.Disposer

/**
 * The [attributesMask] indicated which configuration attributes of [sourceConfig] should reflect to
 * [responseConfig]. This mask should be generated by the flags in [ConfigurationListener], e.g.
 * [ConfigurationListener.CFG_NIGHT_MODE] and [ConfigurationListener.CFG_UI_MODE].
 */
class ModelsProviderConfigurationListener(
  private val model: NlModel,
  private val sourceConfig: Configuration,
  private val responseConfig: Configuration,
  private val attributesMask: Int,
) : ConfigurationListener {
  override fun changed(flags: Int): Boolean {
    val effectiveFlags = flags and attributesMask

    if (effectiveFlags and ConfigurationListener.CFG_ADAPTIVE_SHAPE != 0) {
      val adaptiveShape = sourceConfig.adaptiveShape
      responseConfig.adaptiveShape = adaptiveShape
    }
    if (effectiveFlags and ConfigurationListener.CFG_DEVICE != 0) {
      val device = sourceConfig.device
      responseConfig.setDevice(device, false)
    }
    if (effectiveFlags and ConfigurationListener.CFG_DEVICE_STATE != 0) {
      val sourceState = sourceConfig.deviceState ?: return false
      responseConfig.setDeviceStateName(sourceState.name)
    }
    if (effectiveFlags and ConfigurationListener.CFG_UI_MODE != 0) {
      val uiMode = sourceConfig.uiMode
      responseConfig.uiMode = uiMode
    }
    if (effectiveFlags and ConfigurationListener.CFG_NIGHT_MODE != 0) {
      val nightMode = sourceConfig.nightMode
      responseConfig.nightMode = nightMode
    }
    if (effectiveFlags and ConfigurationListener.CFG_THEME != 0) {
      val theme = sourceConfig.theme
      responseConfig.setTheme(theme)
    }
    if (effectiveFlags and ConfigurationListener.CFG_TARGET != 0) {
      val target = sourceConfig.target
      responseConfig.target = target
    }
    if (effectiveFlags and ConfigurationListener.CFG_LOCALE != 0) {
      val locale = sourceConfig.locale
      responseConfig.locale = locale
    }
    if (effectiveFlags and ConfigurationListener.CFG_FONT_SCALE != 0) {
      val fontScale = sourceConfig.fontScale
      responseConfig.fontScale = fontScale
    }
    model.displaySettings.setTooltip(responseConfig.toHtmlTooltip())
    return true
  }
}

/**
 * Helper function to register [ModelsProviderConfigurationListener]. The listener will be removed
 * when the given [model] is disposed.
 */
fun registerModelsProviderConfigurationListener(
  model: NlModel,
  sourceConfig: Configuration,
  responseConfig: Configuration,
  attributesMask: Int,
) {
  val listener =
    ModelsProviderConfigurationListener(model, sourceConfig, responseConfig, attributesMask)
  sourceConfig.addListener(listener)
  Disposer.register(model) { sourceConfig.removeListener(listener) }
}
